[00:00] This is a secure line. Authenticate. [00:07] Lima, Whiskey, Niner. [00:17] Message received. [00:20] Amongst the sea of agents, there's a mole. [00:22] We can't openly communicate. I can only trust a select few. [00:37] I need to exchange crucial information without anyone noticing. [00:45] There's a massive yet hidden chain of command operating behind the scenes. I'm only privy to a small part of it. [00:53] There's been too many leaks. [01:03] Stop. We're not here to talk about espionage. [01:06] Believe it or not, the processes on your computer face a similar communication challenge every single day. [01:12] The issue of secure interprocess communication has been a critical part of computer architecture for decades. [01:19] Today we're here to talk about one of the most influential implementations of interprocess communication that affects billions of devices worldwide, the Android Binder. [01:30] Let's get wired in. [01:34] Interprocess communication, Laila Bandroid. [01:39] Alright, I'm going to level with you. [01:41] What we're about to dive into isn't your average tech tutorial. [01:45] We're about to embark on a journey through one of the most complex and most crucial systems in modern mobile computing. [01:52] This video is going to be dense. It's going to be technical. [01:55] And at times it might even be a bit challenging. [01:58] But here's the thing. If you stick with me, if you push through those moments of confusion, you're going to come out the other side with a deep understanding of something that affects billions of devices worldwide. [02:10] You're not just going to learn about Android. [02:12] You're going to understand how modern operating systems coordinate their internal components, how they seamlessly communicate between apps and how they manage to do so without us even realizing it. [02:25] Let's begin with our foundational problem. [02:28] How can two separate programs communicate with each other without compromising the system's security or efficiency? [02:35] In computers, we often have multiple processes running simultaneously, each in its own isolated memory space. [02:42] These processes need to share information with each other and coordinate their actions, much like two spies needing to transfer some critical information between each other. [02:53] Seems deceivingly simple. Just have one process write data somewhere and the other person read it. [03:00] Whoa, did you see that? We just opened up a huge can of worms. [03:05] First of all, how is the other process or spy supposed to know when new data is available? [03:11] What if we both try to write data at the same time? [03:14] How do we make sure that data doesn't get corrupted or tampered with during transfer? [03:19] And how do we maintain security so that no other prying eyes see what we're doing? [03:25] I think we better slow down for a second before we get too deep in the weeds. [03:29] Let's talk about the first thing we need to implement. Process isolation. [03:34] Early computers ran one process at a time, so process isolation was a non-issue. [03:40] But with the advent of multitasking operating systems, we now have to worry about this. [03:45] Think about it. If all processes are open, no data is private. [03:53] Not only that, but if one process crashes, the whole system can crash. [03:59] One of the first computers to implement process isolation was the Atlas supercomputer in 1962, [04:09] which I've actually made a previous video on if you'd like to learn more. [04:13] But how does process isolation work in a modern context and more specifically in Android context? [04:20] At the end of the day, Android is built on top of the Linux kernel, which gives us some core security features for free. [04:27] Each process in a Linux system is assigned a unique process ID or PID for short. [04:33] The PID is used in the kernel to track and manage the process, also ensuring that each process has its own virtual address space. [04:42] The memory management unit of the CPU, along with the Linux kernel, ensures that processes can only access their own allocated memory and not the memory of other processes. [04:54] Now, there can be some tricky exceptions to this, but for the most part, that's how it works. [04:59] Android does something a little special, though, that is a bit unconventional compared to what you would expect from, say, a desktop or server Linux installation. [05:10] By default, for each app that is installed, Android assigns a unique user ID or UID for short. [05:17] In other words, each Android app runs as a separate Linux user. [05:22] Each UID gets its own directory protecting processes and file systems from other applications. [05:29] It's kind of like putting special documents in a folder. [05:36] If I'm program A, we each get our own separate folder to store our own data in. [05:43] Neither of us by default can see the contents of other programs folders. [05:48] We're sandboxed by default. [05:50] And now if program B crashes, I can continue to run just fine. [05:58] So there you have it. We've solved the issue of process isolation, at least at a basic level. [06:03] We have security, but no ability to communicate. [06:08] Let's go back to our spy scenario. [06:10] We have two agents and they need to exchange items with each other. [06:14] What's the simplest way that I can achieve this? [06:16] I could just leave the item here in the open and they're able to stumble across it, especially if they know exactly where to look. [06:24] It's not great from a security standpoint, but it is a start. [06:28] Just like our agents have to communicate, processes in a computer system actually have to communicate all the time. [06:35] One of the earliest examples of interprocess communication came from the IBM System 360 introduced in 1964. [06:43] Its operating system, OS 360, had to manage multiple jobs running concurrently, necessitating some form of job to job communication. [06:52] The solution was simple, albeit primitive. [06:55] Jobs could communicate by reading and writing from a shared area. [06:59] Later, in the 70s, early UNIX systems followed a similar methodology. [07:04] It was quite common for programmers to use the slash temp directory as a common ground for simple interprocess communication. [07:12] This method also aligned well with UNIX's everything is a file philosophy. [07:17] So if we have two processes that are otherwise sandboxed from each other, we now have this special slash temp folder that each of us can read and write from to exchange information. [07:28] Let's think about how this would work in an Android context. [07:31] Say you've written some notes in a note taking app and now you want to send it in your email application, which is a separate sandboxed process. [07:39] One of the simpler ways we could solve this is a variation of the UNIX philosophy. [07:45] In Android, it's fairly common for applications to have read and write access to the SD card directory. [07:51] We could just dump what we need in there and read it when the time comes. [07:55] Let's hop into the computer and examine how this would look on a real system. [07:59] Now, what I've done here is I've created two example Android applications. [08:03] One is a very simple notepad application and the other is a very simple email application. [08:09] And they're going to be using the SD card to send information between the two applications. [08:15] Now, the notepad app is going to write to the SD card and the email app is going to read from the SD card since both applications have access to this shared directory. [08:25] If we take a quick look at the notepad application, you can see it's just writing to SD card notepad shared dot text. [08:32] And then the email application is going to be taking values from SD card notepad shared dot text and then adding that to its display up here. [08:41] Let's take a quick look at what that looks like when it's executing. [08:44] First, let's see. There's nothing inside of our SD card except the regular things. [08:48] There's no shared file. So let's run our notepad application. [08:52] Here we have it. Let's add a note, a special note. [08:56] I have a mission for you. [09:03] And let's send this to our email application. [09:06] Share. You can see we successfully saved this to the SD card. [09:10] So now we have this notepad shared dot text that is now available for the other application to read in. [09:18] Let's go to our email app and see if that worked. [09:20] My email. Sure enough, our email is ready to go. [09:23] I have a mission for you. In case you didn't realize it, we've got a pretty major problem here. [09:27] There's effectively no security. [09:29] Any malicious application that has read write access to the SD card can now spy on all interprocess communication of our primitive example. [09:38] Clearly, a more robust solution is necessary in order to create a secure operating system. [09:44] Agent, we've detected a breach in our communication protocols. [09:48] The dead drop system is compromised. [09:51] We have reason to believe enemy Intel is intercepting our messages. [09:55] Understood. When's our next move, Colonel? [09:57] We're switching to a more secure method. [09:59] I've arranged for a courier to deliver your next mission briefing in person. [10:03] This ensures the Intel reaches you and only you. [10:07] Roger that. When is the rendezvous? [10:09] Now. [10:18] Much like our spy agents, a significant improvement can be made in the security of interprocess communication by sending messages process to process [10:27] instead of just a shared area that anybody could stumble upon. [10:30] It's difficult to say exactly which early computer system was the first to widely implement more sophisticated IPC mechanisms. [10:38] There was a lot of interesting competition between various academic and commercial settings. [10:44] That being said, Multics developed as a collaboration between the two companies. [10:50] In the mid 1960s was one of the earlier systems to implement advanced IPC techniques such as interprocess signaling. [10:58] Later in the 1970s, Bell Labs introduced pipes as the fundamental IPC mechanism of Unix, [11:05] a unidirectional point to point scheme that was developed by the company. [11:11] In today's era of computing, modern operating systems such as Android support more complex interactions between processes. [11:19] Binder is the main IPC system of Android. [11:23] But before we get deeper into how exactly the binder works, let's reestablish the fundamental problem here. [11:30] We've got process isolation. We've got indirect communication. [11:34] Now we want a method of direct communication between processes to improve our security posture. [11:41] Going back to our example notes and email applications, let's talk about the setup. [11:46] Instead of just copying our notes app output to any shared area, we want to use the same method to create a new network. [11:55] Let's talk about the setup. Instead of just copying our notes app output to any shared directory that any application can read from, [12:03] including malicious ones, it would be better to send it point to point. [12:08] We can't go into all the details yet, and this is an oversimplification. [12:12] But what if we imagined a third application, this black box we call the binder that handles all the processing and delivery of messages for us. [12:22] That way, the notes app can communicate with the email app seemingly directly, with our special courier making sure our messages get to the right place. [12:31] Let's look at some code. Now I've added the next level of sophistication inside of my example notepad app and example email app so that we can facilitate direct app to app communication. [12:42] This way, we don't have to use the SD card as a shared directory that any application could potentially get access to. [12:49] If we take a look at the email code, there's a brand new communication service that's been added to the code, and this is going to be able to handle messages directly from incoming applications. [13:00] You can see we're using our special binder to be able to facilitate this kind of communication. [13:06] If we go over to our notepad app, we have a connection that's going to be made to this service that's being exposed inside of the email application. [13:15] It's going to be able to connect to this service, bind to it successfully, and then be able to send messages directly to that email application. [13:24] We're even going to be able to see that the notepad app can now directly trigger the email application instead of having to go around through different applications and go notepad and then email. [13:35] Let's execute our new applications. [13:39] I'm going to go over to my emulator, and first of all, we have our new version of the notepad application. [13:45] So let's type a special message. [13:48] I have a mission for you. [13:53] And now before we had to send this, write this to the SD card, and then open up the email application ourselves. [13:59] But here we can just click share. [14:02] And now we directly have our special message inside of our email application. [14:06] All this is well and good, but we're making some pretty heavy assumptions here. [14:10] What is this mysterious program? Who is delivering these messages? [14:14] And why do I, as the program, know so little of what's happening behind the scenes? [14:27] Much like our hidden courier delivering messages between agents, Android has a courier of its own. [14:33] Binder is the main interprocess communication system for Android, but it actually predates Android by a significant amount. [14:40] Binder started off as a project called OpenBinder by B-Ink for their BOS operating system at the tail end of the 1990s. [14:49] B-Ink was then acquired by Palm Inc., known for their personal digital assistants, most famously Palm Pilot. [14:58] Palm eventually split off a subsidiary to license their mobile operating system, Palm OS. [15:04] And development of OpenBinder continued under this new Palm Source division. [15:09] Palm ended up switching to Linux instead of a microkernel-based OS, so Binder was then ported over to Linux and open sourced around 2005. [15:19] Diane Hackborn, one of the key engineers of OpenBinder, was hired by Google to join the Android team. [15:26] The Android team quickly realized that a robust yet efficient IPC was needed for their OS. [15:31] Being that OpenBinder was already ported to Linux and their hardware target was a measly 200MHz ARM device, using OpenBinder as the main IPC mechanism for Android was a no-brainer. [15:44] OpenBinder was used as-is in the early versions of Android, but was eventually completely rewritten in 2008. [15:51] Today's Binder may look quite different from those early iterations, however, many of the core principles remain the same. [15:58] That's enough of a history lesson, let's talk about how it works. [16:01] As I mentioned earlier, Binder is the main interprocess communication system for Android. [16:06] It spans across two different worlds, kernel space and user space, to perform its duties. [16:12] The kernel space implementation is necessary to give Binder the permissions it needs to be able to communicate and send messages across processes. [16:21] Remember, we can't use a file system-based interprocess communication mechanism because in Android we lack a world-writable directory from the application side for security reasons. [16:33] The user space portion of the Binder is required so that applications are able to communicate to Binder, much like a mail person, each application sends its interprocess messages, or letters, over to Binder in user space. [16:47] Binder is implemented in user space as classes inside the Android framework that applications can call whenever they have a message for another app. [16:56] The kernel space area of the Binder is actually implemented as a kernel driver, which handles many low-level operations. [17:03] Managing memory and transmitting data across processes are all handled in kernel space. [17:09] The binder driver in the kernel creates a file, known as a device file, at slash dev slash binder, [17:16] which serves as the gateway for processes in user space to send commands and data to the binder driver. [17:23] Classes inside the Android system make the direct IOCTL system calls to this file to send messages. [17:30] This shields application developers from the complexity of direct communication. [17:36] Instead, devs can use high-level Android APIs, which act as a proxy, handling the IPC operations underneath. [17:44] This way, app devs can focus on application logic instead of all the technical details of interprocess communication. [17:51] Pretty neat, right? Let's take a look at where the real binder file is located on an Android device. [17:57] I currently have my Android emulator running over here, and so I'm going to get a shell to that. [18:02] Let's do ADB shell, then run a super user, and let's change directories to our slash dev directory, [18:10] and then list out all the files and folders inside of this directory. [18:15] And I'm going to grab for anything binder related. Here we go. [18:21] So here you can see our binder gateway file to the binder driver. [18:26] Now you may also notice there are multiple other binder related files in this directory. [18:31] The slash dev slash binder file is used for general purpose binder communication across apps and services, [18:39] but sometimes there are also other device files for hardware specific needs, for example, [18:45] or vendor specific needs for binder communication. [18:48] Now even though there are sometimes different binder device files exposed, [18:52] they still interface with the same binder driver underneath. [19:08] By routing all of our agents' communication through headquarters, [19:13] we've successfully solved the issue of our assets otherwise being isolated from each other. [19:18] The security risks are now mitigated, and the burden of safeguarding messages now falls on HQ, [19:23] not the individual agents. [19:25] But if I'm being pretty honest, it's getting quite overwhelming here. [19:29] Messages of various data types are flowing in from agents' databases, [19:33] SD cards, phone calls, letters, secure radio transmissions, and more. [19:38] We don't really have a centralized process to handle this amount of data [19:42] or to route information in a logical manner. [19:45] There's got to be a better way. [19:48] Let's think about this from a computing perspective. [19:52] Now that we've got an actual mechanism for sending messages back and forth, [19:56] we can actually use this to send messages back and forth. [20:00] Now that we've got an actual mechanism for sending messages back and forth [20:04] between applications using the Android binder, [20:07] we still need to establish some sort of organizational process. [20:11] And there's a few different topics that we need to consider. [20:15] How do we decide what order to send messages in? [20:18] Also, how do we keep track of when messages have already been sent, [20:22] or even store messages that still need to be sent? [20:25] Among the various data structures available to us, [20:28] this is probably the most logical choice. [20:31] To give an overview, a queue is a concept in computer science [20:34] for handling data in a specific order. [20:37] Standard queues work in a first-in, first-out order, or FIFO for short. [20:42] Essentially, this means that the first item to arrive [20:46] is also going to be the first item processed and then removed. [20:53] In the context of Android's binder, [20:56] it means that messages are going to be processed [20:59] in the order in which they have been received. [21:01] The binder driver oversees these message queues [21:04] for every single Android app or service [21:07] that wants to make an interprocess communication request. [21:10] Going back to our spy analogy, [21:13] think of it like a list of messages from each agent [21:16] that needs to be organized and processed. [21:19] Generally, each binder object in a process is allocated [21:22] an incoming queue and an outgoing queue. [21:25] Think of it like your inbox and outbox. [21:28] The outgoing queue stores and manages messages [21:31] generated by the current process that are destined for other processes. [21:35] Conversely, the inbound queue collects and holds messages [21:39] sent by other processes that are intended for the current process to receive. [21:43] Each message request is encapsulated as a transaction. [21:47] Each transaction contains a parcel, [21:50] which is a data structure that stores the actual payload and metadata. [21:54] This parcel acts as a standardized container [21:57] for serializing and deserializing data types [22:00] across process boundaries. [22:03] The binder driver is like headquarters. [22:06] It serves as the central manager for processing all IPC transactions [22:10] sent over the device. [22:13] Whew, that was a lot. [22:16] One extra note for you Android developers out there. [22:19] Each Android application or service making IPC requests [22:23] actually creates a dedicated binder object [22:26] that serves as a proxy for communication [22:29] with the binder driver on the backend. [22:32] In other words, going back to our spy scenario, [22:35] HQ handles all the behind-the-scenes work, [22:38] sorting, routing, and delivering messages, [22:41] but each agent only needs to interact with HQ to do so. [22:45] Pretty neat, right? [22:49] If HQ only accepted one type of data, [22:52] it would severely limit the information that could be shared, [22:55] making some missions impossible. [22:58] Agents should be able to send whatever type of intelligence [23:01] they gather without limitations. [23:04] The data is stored in a container, [23:07] which is a container that is used to store data [23:10] and is used to store data. [23:13] The data is stored in a container, [23:16] and the data is stored in a container [23:19] that is used to store data. [23:22] The data is stored in a container [23:25] that is used to store data. [23:28] At each HQ, we have to efficiently process [23:31] diverse information without needing separate divisions [23:34] for each data type. [23:37] Similar to how the agency is able to process [23:40] diverse forms of information from their operatives, [23:43] we have the ability to process data [23:46] from the agency itself. [23:49] The data is stored in a container [23:52] that is used to store data. [23:55] The data is stored in a container [23:58] that is used to store data. [24:01] It's a little different from the data [24:04] that we can use to process data. [24:07] The data is stored in a container [24:10] that is used to store data. [24:13] Partial objects also support custom objects [24:16] created and defined by Android developers. [24:18] It's kind of like letting our spy agents [24:21] give HQ custom data. [24:24] As long as they tell HQ how to decrypt [24:27] their messages, almost anything goes. [24:30] To send custom data in Android, [24:33] developers simply need to implement a special interface [24:36] called parcelable, which is provided by the Android framework. [24:39] how it should be handled. [24:40] Serialization and flattening of parcel data [24:43] are optional techniques that a developer can [24:45] use for additional optimization. [24:48] It's really the best of both worlds. [24:50] The Android framework provides methods [24:52] to simplify the process of writing and reading [24:54] data from parcels. [24:56] But developers also have flexibility [24:58] for how they implement these for their particular needs. [25:02] Going back to our spy scenario, it's [25:03] kind of like how HQ can give agents suggestions and tooling [25:07] for sending their messages. [25:09] But if they need something more custom, [25:11] they still have the ability to do so. [25:15] Skilled as they may be, we don't expect our agents [25:18] to be experts in everything. [25:20] Hence why, here at HQ, we equip our operatives [25:23] with a covert radio transmission system. [25:25] Welcome. [25:26] Channel load one. [25:31] This system abstracts away many of the complex security [25:34] steps they would normally have to take to communicate with us. [25:37] As long as the agent sends us the message [25:39] in the format we're expecting, it's [25:41] a speedy way to get a message to HQ without additional fuss. [25:47] Remember when we were talking earlier [25:49] about all the different ways Android developers can [25:51] interact with parcel objects? [25:54] It can get pretty brittle and challenging [25:56] to interface with these low-level implementations [25:58] directly. [26:00] Wouldn't it be nice if we had some sort of abstraction, [26:03] something like a wrapper? [26:06] One of the most used wrappers around Binder [26:09] includes a very special message type in Android, intents. [26:13] Much like the covert radio systems [26:15] that HQ gives the agents, intents [26:18] are a quick way to transmit data that gets [26:20] rid of a lot of the hard stuff. [26:23] Intents are one of the most common methods [26:25] for IPC within Android. [26:27] Services, applications, and even components [26:29] inside of applications use intent objects [26:32] to transmit data. [26:33] For example, let's say you're in the Yelp app [26:36] and you decide to try out a new sushi restaurant. [26:39] You click on the address of the restaurant, [26:41] and it magically opens up the address in Google Maps. [26:44] How did Google Maps know it needed to be open? [26:47] And how did it know which address to go to? [26:50] Underneath, the Yelp application is simply [26:52] sending an intent message defining [26:54] what kind of action needs to be performed, [26:56] as well as what data is relevant, which in this case [26:59] is the destination address. [27:01] Google Maps is listening for these messages [27:03] and has defined that it's going to open up [27:06] the address defined inside of the intent object. [27:09] So next time you're using an Android phone, [27:12] take a moment to notice that most of these interactions [27:15] between applications are silently calling [27:17] the binder on the back end. [27:26] This is your new identity. [27:28] Memorize every detail. [27:30] Your name, your history, they no longer exist. [27:34] This is who you are now. [27:36] The document also contains a secure ID code. [27:39] That cipher is how we will deliver messages to you. [27:43] This radio is your lifeline. [27:45] Missions will get routed through that radio, [27:47] encrypted through your cipher. [27:50] We have all your information in our database. [27:53] The old you dies today. [27:55] Don't mess this up. [28:00] While we've addressed message formatting, [28:02] storage, and transmission, [28:03] we still have other challenges to consider. [28:06] One of the more interesting aspects [28:08] of interprocess communication [28:10] is message routing and service discovery. [28:13] A fascinating historical example of service discovery [28:16] comes from an experimental operating system [28:19] developed at Xerox's park in the late 1970s. [28:23] The researchers created an operating system called Cedar [28:26] built on top of the Mesa programming language. [28:29] One of Cedar's key features [28:31] was a component called clearing house. [28:34] Clearing house was a network-wide [28:35] naming and authentication system. [28:38] Clearing house provided a hierarchical namespace [28:41] for naming and locating resources, [28:43] including services, across a distributed network. [28:47] Processes on the system could use clearing house [28:50] to look up and connect to services [28:52] across the distributed system. [28:54] Let's examine this from the perspective [28:55] of the centralized manager of Android, the binder. [28:59] Picture this, you have a ton of messages formatted, [29:02] queued up, and otherwise ready to go. [29:05] As the message manager, [29:06] how do you know where to deliver each message? [29:09] To effectively route the messages, [29:11] each message requires a target location. [29:14] Message recipients would need to register beforehand [29:17] with address and delivery details [29:19] in order to receive their messages. [29:22] In Android, this is solved [29:23] with something called service manager. [29:26] The service manager serves as the centralized registry [29:29] where both system services and applications [29:33] can register themselves to receive messages via the binder. [29:36] Each client must register under a unique name, [29:39] much like how each agent has a unique contact address [29:43] so that other processes can specify [29:45] their service name as the target. [29:48] When an app or service needs to send a message [29:50] to another service, it queries the service manager [29:53] with the destination service name. [29:56] The service manager then returns a binder object, [29:58] which the sender can then use to communicate [30:01] with the intended recipient. [30:03] Remember, because Android is an open source operating system [30:06] at the end of the day, [30:08] we can take a look at the real source code [30:10] to see how service discovery works [30:12] in a modern operating system. [30:14] Here we're taking a look at the actual Android source code. [30:17] Remember those unique names [30:19] that services have to register under? [30:21] This is how the actual Android system [30:23] names common services running on the device. [30:26] If you're an Android developer, [30:28] some of these might look familiar to you. [30:31] There is the phone service, for example, [30:33] that is registered for getting the telephony manager. [30:37] This lets you use all the different telephony features [30:40] on the device, like making a phone call, for example. [30:43] If we scroll down, we can find the clipboard service [30:47] for retrieving the clipboard manager. [30:50] This lets you access or modify contents [30:53] of the Android clipboard. [30:54] And there are so many other services on here as well. [30:58] If you're curious, try looking at this file [31:00] in the Android source code [31:02] and check out all the different services [31:04] that you never knew were running [31:05] in the background of your device. [31:07] You can find relevant links [31:09] in the comments section of this video. [31:12] Who is this? What's going on? [31:14] WIMA, WISKY, POUR. [31:16] Access denied. [31:17] Unauthorized attempt detected. [31:19] Override. [31:21] Warning. Unauthorized access detected. [31:24] Security protocols engaged. [31:26] This incident will be reported. [31:28] Insufficient clearance for classified data. [31:31] Terminating connection. [31:33] That transmission was not successful. [31:35] The device is not working. [31:37] The device is not working. [31:39] That transmission was not on any of our approved channels. [31:42] It could be the enemy trying to... [31:51] In the Android world, despite the centralized manager's [31:54] comprehensive knowledge of all service locations [31:56] within the system, [31:58] communication between services and applications [32:00] is restricted based on predefined access rules. [32:04] This is an essential component [32:07] of maintaining the security of the overall system. [32:09] Services can specify permissions [32:11] required for communication. [32:13] Clients must then request the appropriate privileges [32:16] before attempting to interact with these services. [32:19] The Android system verifies the necessary permissions [32:22] are met prior to initiating [32:24] any requested binder transactions. [32:26] Applications are able to declare the permissions [32:29] they intend to request [32:31] within their main configuration file [32:33] known as the Android manifest. [32:37] We have an urgent request for Agent 17. [32:40] Send them the mission data immediately. [32:42] Negative, Colonel. [32:44] Agent 17 is currently engaged, unable to comply. [32:47] Unacceptable. [32:49] Find me an alternative now. [32:51] This is time sensitive. [32:53] Roger that. [32:55] Scanning for available operatives in the vicinity. [32:57] Looks like several agents are on standby [32:59] awaiting deployment. [33:01] Good. [33:03] I expect results. [33:05] Don't let me down. [33:07] Understood, Colonel. [33:09] I'll transmit the data to the most suitable candidate shortly. [33:11] Over and out. [33:13] We previously talked about how the binder uses [33:16] a queue-based architecture [33:18] for handling the transmission of messages. [33:20] The queue works well for ensuring messages [33:22] get received in a logical manner. [33:24] However, this approach raises some questions [33:26] about efficiency. [33:28] After all, we are targeting mobile devices, [33:30] so resource usage is of the utmost importance. [33:34] If only there were a more optimal way [33:36] to handle message processing [33:38] while maintaining order integrity. [33:40] Thankfully, there is. [33:42] In order to bypass the inefficiencies [33:44] of transmitting only one message at a time, [33:46] the binder uses thread pools [33:48] to manage incoming message requests. [33:52] Thread pools allow the binder to add concurrency [33:54] and consequently the ability to process [33:56] multiple transactions simultaneously. [33:58] It works by having a pool of worker threads available [34:00] and inputting the message. [34:02] The pool also has worker threads available [34:04] at any given time, [34:06] dedicated to handling binder transactions as they come in. [34:08] This is similar to our spy scenario [34:10] where HQ keeps multiple agents [34:12] available for incoming messages. [34:14] When a new transaction or mission arrives, [34:16] it is assigned to one of the available threads, [34:18] aka agents, inside of the pool. [34:20] Once a transaction task is dispatched [34:22] to a processing thread, [34:24] it's also removed from the queue. [34:26] This allows the transaction queue [34:28] to maintain its original FIPO processing order. [34:30] Of course, just like HQ doesn't have infinite agents [34:32] to work with, [34:34] Android doesn't have an infinite amount of worker threads [34:36] in the pool. [34:38] There is still a maximum limit, [34:40] but processing messages in this way [34:42] is significantly more efficient [34:44] than transactions only being processed [34:46] one message at a time. [34:48] We've got a problem. [34:50] Agent 17 isn't responding to our signals. [34:52] Do you think they're burned? [34:54] No. [34:56] We're not. [34:59] Do you think they're burned? [35:01] It's possible. [35:03] Your team has been continuously sending intelligence [35:05] to a dead agent. [35:07] Stop wasting resources. [35:09] Your messages aren't going anywhere. [35:11] Understood. [35:13] Set up a system for your other agents [35:15] to have a dead man's switch or signal of some sort. [35:17] We have to have an indication [35:19] of when something is wrong. [35:21] Roger that, Colonel. I'll implement it right away. [35:23] Good. [35:25] We can't afford to lose any more intel. [35:27] We need to be alert out there. [35:29] While we've covered the essential aspects [35:31] of a fully functioning [35:33] interprocess communication system, [35:35] there are additional optimizations worth considering. [35:37] As computer scientists, [35:39] we should always be cognizant [35:41] of resource usage and efficiency, [35:43] especially on mobile platforms [35:45] where there are size, weight, and power limitations. [35:47] Much like the spy scenario, [35:49] we don't want applications communicating [35:51] with target services [35:53] that are otherwise dead or failing [35:56] that are otherwise dead or failed. [35:58] It's just a waste of resources. [36:00] Historically, one of the first systems [36:02] to handle death notifications in IPC [36:04] was the MAC Colonel, [36:06] developed at Carnegie Mellon University [36:08] in the mid-1980s. [36:10] In MAC, when a port, [36:12] think of it like an endpoint, was destroyed, [36:14] MAC would send a notification [36:16] to processes holding send rights [36:18] to that port. [36:20] Many of the concepts introduced in MAC [36:22] influenced much of the modern [36:24] operating system design. [36:26] In fact, if you're an iOS developer [36:28] or MAC developer, [36:30] you might recognize that name right away. [36:32] Ever heard of MACO binaries? [36:34] Apple's XNU kernel [36:36] is a derivative of the original [36:38] MAC Colonel from the mid-80s. [36:40] So you'll occasionally see terminology [36:42] related to the original system. [36:44] Alright, so now we know the history [36:46] of death notifications, [36:48] let's jump back into the modern era [36:50] and take a look at an Android example. [36:53] If an application is registered to communicate [36:55] with a target service that has died, [36:57] continued transactions would be [36:59] pretty inefficient. To fix this, [37:01] Binder uses a special kind [37:03] of notification, known as a [37:05] death notification, that allows clients [37:07] to gracefully handle unexpected [37:09] issues in the target process [37:11] they're communicating with. [37:13] The client app then attaches [37:15] a death recipient to the binder, [37:17] which lets the client app run [37:19] code to clean up resources, [37:21] or even reset the connection if the connected [37:23] process dies. This capability [37:25] allows applications to conserve [37:27] resources when errors happen. [37:29] Let's look at a real example. [37:31] Let's go back to our example, email [37:33] and notepad applications. [37:35] Now previously we had successfully [37:37] implemented app-to-app communication [37:39] using the binder. [37:41] But now we need to attach a death recipient [37:43] inside of our notepad application [37:45] to figure out when the email [37:47] service dies. And that's exactly [37:49] what we've got here inside of the code. [37:51] We have our returned binder object, [37:53] and we're attaching a death recipient [37:55] so that we can run code inside [37:57] of this client application [37:59] once the service dies. [38:01] Here we can see we're just running a simple [38:03] toast so that we can pop up a notification [38:05] on the screen to alert [38:07] the user that this service has [38:09] died. And if we take a look at our [38:11] example email application, I've [38:13] created an example purposeful [38:15] crash so that we can get our [38:18] service to die after 4 seconds [38:20] and trigger this death notification [38:22] inside of our notepad app. [38:24] Let's jump in and see what that looks like. [38:26] Let's open up the final versions of our [38:28] email and notepad applications [38:30] with the death recipient stored inside [38:32] of the notepad application connected [38:34] to the email service. [38:36] I'm going to open up my email service first. [38:38] And remember this has the [38:40] 4 second delay once a client [38:42] attaches so that we can [38:44] demonstrate that death notification occurring. [38:46] Now let's go to our notepad application [38:48] and that's going to automatically connect [38:50] to our email service. [38:52] Here we go. We can start typing our notes [38:54] but let's just wait for a second and see. [38:56] Yep, here we go. [38:58] We have our toast notification email service [39:00] died. So this is letting [39:02] us know that our email notification [39:04] app has actually crashed [39:06] and then the service that our client [39:08] notepad application was connected to [39:10] via the binder is not able to [39:12] connect anymore. With great power [39:15] comes great responsibility. [39:17] The centralized communications manager [39:19] is necessary but opens up [39:21] a large potential vulnerability. [39:23] In Android, the binder has [39:25] immense power within the system. [39:27] This also makes it one of the [39:29] largest targets for exploitation [39:31] and abuse. Compromising the [39:33] binder could potentially allow [39:35] a malicious application to gain [39:37] unauthorized access to critical [39:39] system resources and operations. [39:41] This breach could lead to [39:43] wide-ranging control over the device [39:45] affecting security, privacy, [39:47] and overall functionality. [39:49] Binder's size and complexity [39:51] exposes a large attack [39:53] surface. Its constant [39:55] parsing and transferring of application [39:57] data sent via messages [39:59] makes the binder a super ripe target. [40:01] Early versions of the [40:03] Android binder were susceptible to [40:05] transaction forgery, allowing [40:07] malicious applications to impersonate [40:09] other apps or services [40:12] and get access to data they shouldn't. [40:14] Over the years, there have been several other [40:16] severe binder vulnerabilities. [40:18] Some of which have even resulted [40:20] in malicious apps gaining power [40:22] to obtain arbitrary kernel read [40:24] and write privileges. [40:26] The severity of these vulnerabilities [40:28] is really as high as the privileges [40:30] that the binder has over the entire [40:32] Android system. [40:34] Project Zero, a vulnerability [40:36] research group at Google, has published [40:38] an interesting example of binder abuse [40:40] in the wild. In any case, security [40:42] is always a major concern [40:44] for any IPC system, [40:46] and Android is no exception. [40:48] It may be difficult to stay one [40:50] step ahead of the bad guy, but a [40:52] robust system design can mitigate [40:54] many of the risks that bad [40:56] actors could otherwise abuse. [40:58] As we've seen, the [41:00] Android binder is a powerful and complex [41:02] system that forms the backbone [41:04] of interprocess communication [41:06] in one of the world's most popular [41:08] operating systems. [41:10] With the rise of increasingly powerful [41:12] mobile hardware, I'm excited to see [41:14] what innovations the future will hold [41:16] for IPC systems. [41:18] Imagine this, enhanced security [41:20] features to combat ever-evolving [41:22] threats, more efficient data transfer [41:24] methods to conserve battery life, [41:26] or maybe even some ML [41:28] optimized message prioritization [41:30] could all be things we experience [41:32] in the near future. [41:34] But here's the exciting part, you don't [41:37] have to be a Google engineer to contribute [41:39] to this future. There's a whole [41:41] world of open source code out there. [41:43] Whether you're a seasoned [41:45] developer or just starting out, [41:47] understanding interprocess communication [41:49] systems like the binder [41:51] gives you a powerful toolkit. [41:53] And it's an often neglected area [41:55] of computer science that deserves [41:57] more attention. Remember, every [41:59] great technological advancement starts [42:01] with curiosity and a willingness [42:03] to dive deep into how things work. [42:05] The next breakthrough in IPC could come [42:07] from anyone, maybe even you. [42:09] If you're intrigued by what you've learned today, [42:11] I encourage you to explore further. [42:13] Check out the Android documentation, [42:15] experiment with different IPC [42:17] methods, read some research papers, [42:19] and don't be afraid to push [42:21] the boundaries of what's possible. [42:23] Thanks for joining me on this deep dive [42:25] into the Android binder. If you enjoyed [42:27] this style of content, don't forget to subscribe, [42:29] and until next time, Lori Wired out. [42:35] Thanks for watching.